package emergence.resource.inputfile;

import emergence.game.gfx.ColoredSprite;
import emergence.game.gfx.Colors;
import emergence.game.gfx.Sprite;
import emergence.game.gfx.SpriteSheet;
import emergence.resource.Resources;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

import util.Logger;
import util.Nifty;

public class ConfigFile {

    protected String filePath;
    protected File file;

    protected static final Logger logger = Logger.getDefaultLogger();
	
    protected Map<String, ConfigNode> nodes = new HashMap<>();

    public ConfigFile(String filePath) {
        this.filePath = filePath;
        this.file = new File(filePath);
    }

    public ConfigFile(File file) {
        this.file = file;
        this.filePath = file.getAbsolutePath();
    }

    public String filePath() {
        return filePath;
    }

    public void readData() {
        try {
            Scanner initScan = new Scanner(file);
            Scanner scan = initScan.useDelimiter("\\Z");

            processData(scan.next().split("\n"));

            scan.close();
            initScan.close();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
            logger.log(e);
        }
    }

    private void processData(String[] data) {
        int bracketCount = 0;
        boolean inNode = false;
        int nodeStartIndex = 0;
        for (int index = 0; index < data.length; index++) {
            String line = Nifty.cleanComments(data[index], "//").trim();

            if (line.equals("")) {
                continue;
            }

            if (line.equals("{")) {
                bracketCount++;
                if (!inNode) {
                    inNode = true;
                    nodeStartIndex = index;
                }
            }

            if (line.equals("}")) {
                bracketCount--;

                if (bracketCount == 0) {
                    String[] nodeData = Arrays.copyOfRange(data, nodeStartIndex + 1, index);
                    inNode = false;

                    nodes.put(data[nodeStartIndex - 1].trim().toUpperCase(), new ConfigNode(nodeData));
                }
            }
        }

    }

    public boolean hasNode(String key) {
        return nodes.containsKey(key);
    }

    public ConfigNode node(String key) {
        if (hasNode(key)) {
            return nodes.get(key);
        }
        return null;
    }

    protected ColoredSprite getColoredSpriteFrom(ConfigNode node) {
        SpriteSheet sheet = Resources.getSpriteSheet(node.value("SPRITESHEET"));
        int xPos = Integer.parseInt(node.value("XPOS"));
        int yPos = Integer.parseInt(node.value("YPOS"));
        int width = Integer.parseInt(node.value("WIDTH"));
        int height = Integer.parseInt(node.value("HEIGHT"));
        int color1 = Integer.parseInt(node.value("COLOR1"));
        int color2 = Integer.parseInt(node.value("COLOR2"));
        int color3 = Integer.parseInt(node.value("COLOR3"));
        int color4 = Integer.parseInt(node.value("COLOR4"));

        Sprite sprite = sheet.getSprite(xPos, yPos, width, height);

        return new ColoredSprite(sprite, Colors.get(color1, color2, color3, color4));
    }
    
    public static class ConfigNode {

        private Map<String, ConfigNode> nodes = new HashMap<>();
        private Map<String, String> values = new HashMap<>();

        public ConfigNode(String[] data) {
            int bracketCount = 0;
            boolean inNode = false;
            int nodeStartIndex = 0;
            for (int index = 0; index < data.length; index++) {
                String line = Nifty.cleanComments(data[index], "//").trim();

                if (line.equals("")) {
                    continue;
                }

                if (line.equals("{")) {
                    bracketCount++;
                    if (!inNode) {
                        inNode = true;
                        nodeStartIndex = index;
                    }
                }

                if (line.equals("}")) {
                    bracketCount--;

                    if (bracketCount == 0) {
                        String[] nodeData = Arrays.copyOfRange(data, nodeStartIndex + 1, index);
                        inNode = false;

                        nodes.put(data[nodeStartIndex - 1].trim().toUpperCase(), new ConfigNode(nodeData));
                    }
                }

                if (bracketCount == 0 && line.contains("=")) {
                    int indexOfEquals = line.indexOf('=');
                    String key = line.substring(0, indexOfEquals).trim().toUpperCase();
                    String value = line.substring(indexOfEquals + 1, line.length()).trim();
                    values.put(key, value);
                }
            }
        }

        public boolean hasNode(String key) {
            return nodes.containsKey(key);
        }

        public boolean hasValue(String key) {
            return values.containsKey(key);
        }

        public ConfigNode node(String key) {
            if (hasNode(key)) {
                return nodes.get(key);
            }
            return null;
        }

        public String value(String key) {
            if (hasValue(key)) {
                return values.get(key);
            }
            return null;
        }

        public Map<String, ConfigNode> getNodes() {
            return nodes;
        }

        public Map<String, String> getValues() {
            return values;
        }
    }

}
